/*
* @Authors: Morozan Ion & Sandu Andreea
*/
package rest;
import classes.DAO;
import classes.Flight;
import classes.Reservation;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
@Path("/v1")
public class ReservationResource {
@Context
private UriInfo uriInfo;
/*
* GET http://localhost:8080/api/v1/flights -> returns all flights
*
* GET http://localhost:8080/api/v1/flights?from=Prague ->
* returns just the flights that have from_destionation "Prague".
*
* GET http://localhost:8080/api/v1/flights?from=Prague&to=Barcelona ->
* returns just the flights that have from_destionation "Prague" and
* destination "Barcelona".
*
* GEThttp://localhost:8080/api/v1/
* flights?from=Antalya&to=Barcelona&depart=01-NOV-2012&return=07-NOV-2012
* returns just the flights that have from_destionation "Antalya",
* destination "Barcelona", departure date "01-NOV-2012" and return date
* "07-NOV-2012".
*/
@Path("/flights")
@Produces(MediaType.APPLICATION_XML)
@GET
public Response getAllFlights(@QueryParam("from") String from,
@QueryParam("to") String to,
@QueryParam("depart") String departing,
@QueryParam("return") String returning,
@QueryParam("properties") String properties) {
ResponseBuilder builder = Response.status(Response.Status.OK);
DAO db = DAO.getInstance();
GenericEntity<List<Flight>> entity = null;
/*PROJECTION*/
/* Projection GEThttp://localhost:8080/api/v1/flights?properties=from,to*/
if (properties != null) {
/* creating a list with all the disered fileds from properties */
ArrayList<String> tags = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(properties, ",");
while (st.hasMoreTokens()) {
tags.add(st.nextToken());
}
/*get all flights from the DB*/
List<Flight> allFlights = db.getAllFlights();
int i;
/* create the Xml file with the desired fields*/
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = null;
try {
documentBuilder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException ex) {
Logger.getLogger(ReservationResource.class.getName()).
log(Level.SEVERE, null, ex);
}
Document document = documentBuilder.newDocument();
Element RootElement = document.createElement("flights");
document.appendChild(RootElement);
/*extract all the fields from tags and create the xml tree*/
for (i = 0; i < allFlights.size(); i++) {
Element Node = document.createElement("flight");
RootElement.appendChild(Node);
if (tags.contains("from")) {
Element em = document.createElement("flightFrom");
em.appendChild(document.createTextNode(allFlights.get(i).getFlightFrom()));
Node.appendChild(em);
}
if (tags.contains("to")) {
Element em = document.createElement("flightTo");
em.appendChild(document.createTextNode(allFlights.get(i).getFlightTo()));
Node.appendChild(em);
}
if (tags.contains("depart")) {
Element em = document.createElement("departureDate");
em.appendChild(document.createTextNode(allFlights.get(i).getDepartureDate()));
Node.appendChild(em);
}
if (tags.contains("return")) {
Element em = document.createElement("returnDate");
em.appendChild(document.createTextNode(allFlights.get(i).getReturnDate()));
Node.appendChild(em);
}
}
builder.entity(document);
/*SELECTION*/
/* GEThttp://localhost:8080/api/v1/
* flights?from=Antalya&to=Barcelona&depart=01-NOV-2012&return=07-NOV-2012
* */
} else if (from != null && to != null && departing != null && returning != null) {
entity = new GenericEntity<List<Flight>>(
db.getFlightsFromToDepartureReturn(from,
to,
departing,
returning)) {
};
builder.entity(entity);
/*SELECTION*/
/* GET http://localhost:8080/api/v1/flights?from=Prague&to=Barcelona */
} else if (from != null && to != null && departing == null && returning == null) {
entity = new GenericEntity<List<Flight>>(db.getFlightsFromTo(from,
to)) {
};
builder.entity(entity);
/*SELECTION*/
/* GET http://localhost:8080/api/v1/flights?from=Prague */
} else if (from != null && to == null && departing == null && returning == null) {
entity = new GenericEntity<List<Flight>>(db.getFlightsFrom(from)) {
};
builder.entity(entity);
/*SELECTION*/
/* GET http://localhost:8080/api/v1/flights */
} else if (from == null && to == null && departing == null && returning == null) {
entity = new GenericEntity<List<Flight>>(db.getAllFlights()) {
};
builder.entity(entity);
} else {
builder = Response.status(Response.Status.BAD_REQUEST).
entity(HandlingMessage("Error", "error",
"Wrong selection or projection! The accepted tags are:"
+ "from, to, depart, return or properties(selection)"));
}
return builder.build();
}
/*
* Retrieving specific flight by flight number
*
* GET http://localhost:8080/api/flights/234
*/
@GET
@Produces(MediaType.APPLICATION_XML)
@Path("/flights/{id}")
public Response getFlightById(
@PathParam("id") String id) {
ResponseBuilder builder = Response.status(Response.Status.OK);
DAO db = DAO.getInstance();
if (db.getFlightById(id) != null) {
builder.entity(db.getFlightById(id));
} else {
builder = Response.status(Response.Status.NOT_FOUND).
entity(HandlingMessage("Error", "error",
"Flight not found! Check the flight number again!"));
}
return builder.build();
}
/*
* Update or creating using PUT method
* The athoer application send me the ID of the reservation
* and then I create or I update the information into the DB.
*
* curl -v http://localhost:8080/api/flights/6 -X PUT -d @reservation.xml
* -H "Content-Type: application/xml"
*/
@PUT
@Consumes(MediaType.APPLICATION_XML)
@Path("/reservation/{id}")
public Response addReservationWithId(JAXBElement<Reservation> reservation,
@PathParam("id") Long id) {
DAO db = DAO.getInstance();
ResponseBuilder builder = null;
Reservation newReservation = reservation.getValue();
/* means that the ID of the reservation was included in link
* so i will update this reservation => the xml file does not
* need to have the resrvation id in his content otherwise it has to
*/
if (id != null && id.equals(newReservation.getId())) {
newReservation.setId(id);
} else {
builder = Response.status(Response.Status.BAD_REQUEST).
entity(HandlingMessage("Error", "error",
"The ID of the reservation is not valid or don't exists!"
+ "The mentioned id should be the same with the one from"
+ "the received xml file"));
return builder.build();
}
if (isReservationContentCorrect(newReservation)) {
/* Update / Create reservation */
db.saveReservation(newReservation);
/* set the status that the content was added to DB */
builder = Response.status(Response.Status.CREATED).
entity(HandlingMessage("Success", "success",
"Your reservation was successfully updated!"));
} else {
builder = Response.status(Response.Status.UNSUPPORTED_MEDIA_TYPE).
entity(HandlingMessage("Error", "error",
"The content of the reservation is incomplete!"));
}
return builder.build();
}
/*
* Creating new reservation using POST method based on
* XML file received
*
* curl -v http://localhost:8080/api/flights -X POST -d @reservation.xml
* -H "Content-Type: application/xml"
*/
@POST
@Consumes(MediaType.APPLICATION_XML)
@Path("/reservation")
public Response addFlight(JAXBElement<Reservation> reservation) {
DAO db = DAO.getInstance();
ResponseBuilder builder = null;
Reservation addNewReservation = reservation.getValue();
Long ReservationId = addNewReservation.getId();
/* if the Xml file contains all the req fields and it has a reservation
* number and it's the same like the one in the link then it can be updated
*/
if (isReservationContentCorrect(addNewReservation)
&& ReservationId != null) {
if (!db.existReservation(ReservationId)) {
db.addReservation(addNewReservation);
URI reservationUri = uriInfo.getAbsolutePathBuilder().
path(addNewReservation.getId().toString()).
build();
builder = Response.status(Response.Status.CREATED).
location(reservationUri).
entity(HandlingMessage("Success", "success",
"Your reservation was successfully added to DB!"));
} else {
builder = Response.status(Response.Status.NOT_ACCEPTABLE).
entity(HandlingMessage("Error", "error",
"The ID of the reservation already exists!"));
}
} else {
builder = Response.status(Response.Status.UNSUPPORTED_MEDIA_TYPE).
entity(HandlingMessage("Error", "error",
"The ID of the reservation is not valid or don't exists! "
+ "The content of the Reservation is incomplete!"));
}
return builder.build();
}
/*
* Deleting a Reservation with a given ID
* The athoer application send me the ID of the reservation
* and then I delete the reservation if existrs from the DB.
*
* curl -v http://localhost:8080/api/reservation/6 -X DELETE -d @reservation.xml
* -H "Content-Type: application/xml"
*/
@DELETE
@Consumes(MediaType.APPLICATION_XML)
@Path("/reservation/{id}")
public Response removeReservationWithId(JAXBElement<Reservation> reservation,
@PathParam("id") Long id) {
DAO db = DAO.getInstance();
Reservation deleteReservation = reservation.getValue();
ResponseBuilder builder;
/* if it's a good request send NO_CONTENT else BADREQ*/
if (db.existReservation(id) && deleteReservation.getId() == id) {
/* if I want to delete a reservation afer a given ID*/
deleteReservation.setId(id);
db.deleteReservation(deleteReservation);
builder = Response.status(Response.Status.NO_CONTENT).
entity(HandlingMessage("Success", "success",
"Your reservation was successfully deleted"));
} else {
builder = Response.status(Response.Status.BAD_REQUEST).
entity(HandlingMessage("Error", "error",
"The ID of the reservation is not valid or don't exists! "
+ "The mentioned id should be the same with the one from"
+ "the received xml file"));
}
return builder.build();
}
/*
* Deleting a Reservation with xml file
* The athoer application send me the xml file with all the information about
* the reservation and then I delete the reservation if existrs from the DB.
*
* curl -v http://localhost:8080/api/reservation -X DELETE -d @reservation.xml
* -H "Content-Type: application/xml"
*/
@DELETE
@Consumes(MediaType.APPLICATION_XML)
@Path("/reservation")
public Response removeReservation(JAXBElement<Reservation> reservation) throws ParserConfigurationException {
DAO db = DAO.getInstance();
Reservation deleteReservation = reservation.getValue();
ResponseBuilder builder = null;
/* if it's a good request send CREATE else BADREQ*/
if (deleteReservation.getId() != null
&& db.existReservation(deleteReservation.getId())) {
db.deleteReservation(deleteReservation);
builder = Response.status(Response.Status.NO_CONTENT).
entity(HandlingMessage("Success", "success",
"Your reservation was successfully deleted"));
} else {
builder = Response.status(Response.Status.BAD_REQUEST).
entity(HandlingMessage("Error", "error",
"The ID of the reservation is not valid or don't exist!"));
}
return builder.build();
}
/**
*
* @param reservation = a reservation made by the client
* @return if the reservation content is correct
*/
private boolean isReservationContentCorrect(Reservation reservation) {
if (reservation.getFrom() != null
&& reservation.getTo() != null
&& reservation.getLeave() != null
&& reservation.getReturning() != null
&& reservation.getPassengers() != null
&& reservation.getName() != null
&& reservation.getFlightNumber() != null) {
return true;
}
return false;
}
/**
*
* @param MessageType Error / Success
* @param MessageTag error / success = type of the xml tag
* @param Message The message that the client will see
* @return
*/
private Document HandlingMessage(String MessageType,
String MessageTag, String Message) {
/* Create the Xml file*/
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = null;
try {
docBuilder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException ex) {
Logger.getLogger(ReservationResource.class.getName()).
log(Level.SEVERE, null, ex);
}
Document doc = docBuilder.newDocument();
Element RootElement = doc.createElement(MessageType);
Element Node = doc.createElement(MessageTag);
Text textNode = doc.createTextNode(Message);
Node.appendChild(textNode);
RootElement.appendChild(Node);
doc.appendChild(RootElement);
return doc;
}
}